package xidian.vlab.service.impl;

import org.openstack4j.model.common.Identifier;
import org.openstack4j.model.compute.Server;
import org.openstack4j.model.compute.VNCConsole;
import org.openstack4j.openstack.OSFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xidian.vlab.config.Properties;
import xidian.vlab.domin.Log;
import xidian.vlab.domin.Room;
import xidian.vlab.domin.User.Student;
import xidian.vlab.domin.User.Teacher;
import xidian.vlab.domin.VMachine;
import xidian.vlab.dto.ListDTO;
import xidian.vlab.dto.QueryDTO;
import xidian.vlab.dto.ResJsonDTO;
import xidian.vlab.dto.VMachineDTO;
import xidian.vlab.repository.RoomRepository;
import xidian.vlab.repository.User.StudentRepository;
import xidian.vlab.repository.VMachineRepository;
import xidian.vlab.service.LogService;
import xidian.vlab.service.VMachineService;
import xidian.vlab.utils.ResUtil;
import org.openstack4j.api.OSClient.OSClientV3;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service("VMachineService")
public class VMachineServiceImpl implements VMachineService {
    @Autowired
    private VMachineRepository machineRepo;
    @Autowired
    private RoomRepository roomRepo;
    @Autowired
    private StudentRepository stuRepo;
    @Autowired
    private LogService logService;
    @Autowired
    private Properties properties;

    @Override
    public ResJsonDTO getList(QueryDTO query){
        ListDTO list = new ListDTO();
        List<VMachineDTO> machineList = new ArrayList<>();
        VMachineDTO vMachine;
        List<VMachine> machines = machineRepo.findAll();
        if (machines.size()>0) {//补充未准备好时无法获取的信息
            OSClientV3 os = OSFactory.builderV3()//管理员token
                    .endpoint(properties.getKeystoneAPI())
                    .credentials("e50212063663477c8e127206180a095e","asdfjkl")
                    .scopeToProject(Identifier.byName("admin"), Identifier.byName("Default"))
                    .authenticate();
            boolean CHANGED = false;
            for (VMachine machine : machines) {
                Server server = os.compute().servers().get(machine.getMid());
                if (server.getStatus() != Server.Status.ACTIVE) {
                    machine.setStatus(server.getStatus().toString());
                    continue;
                }

                if ( machine.getIP() == null ) {
                    CHANGED = true;
                    machine.setIP(server.getAddresses().getAddresses(machine.getRoom().getName()).get(0).getAddr());
                }

                if (CHANGED) {
                    machineRepo.save(machine);
                    CHANGED = false;
                }
            }
        }

        if (query.getAid() != null) {
            machines = machineRepo.findAll();
            for (VMachine machine : machines) {
                vMachine = new VMachineDTO(
                        machine.getMid(),
                        machine.getIP(),
                        machine.getUsername(),
                        machine.getPassword(),
                        machine.getStatus(),
                        machine.getImgName(),
                        machine.getProfile(),
                        machine.getEndTime()
                );
                vMachine.setStudent(machine.getStudent().getName());
                vMachine.setSid(machine.getStudent().getSid());
                vMachine.setTeacher(machine.getRoom().getTeacher().getName());
                machineList.add(vMachine);
            }
            list.setMachineList(machineList);
            list.setTotal(machineList.size());
            return ResUtil.OK(list);
        }
        if (query.getTid()!=null && query.getRid()!=null) {
            Room room = roomRepo.findById(query.getRid()).orElse(null);
            if (room == null) return ResUtil.ERROR("未找到该教室"+query.getRid());
            for (VMachine machine : room.getMachines()) {
                vMachine =  new VMachineDTO(
                        machine.getMid(),
                        machine.getIP(),
                        machine.getUsername(),
                        machine.getPassword(),
                        machine.getStatus(),
                        machine.getImgName(),
                        machine.getProfile(),
                        machine.getEndTime()
                );
                vMachine.setStudent(machine.getStudent().getName());
                vMachine.setSid(machine.getStudent().getSid());
                machineList.add(vMachine);
            }
            list.setMachineList(machineList);
            list.setTotal(machineList.size());
            return ResUtil.OK(list);
        }
        if (query.getSid() != null) {
            Student student = stuRepo.findById(query.getSid()).orElse(null);
            if (student == null) return ResUtil.ERROR();
            for (VMachine machine : student.getMachines()) {
                vMachine = new VMachineDTO(
                        machine.getMid(),
                        machine.getIP(),
                        machine.getUsername(),
                        machine.getPassword(),
                        machine.getStatus(),
                        machine.getImgName(),
                        machine.getProfile(),
                        machine.getEndTime()
                );
                vMachine.setTeacher(machine.getRoom().getTeacher().getName());
                vMachine.setCid(machine.getRoom().getCid());
                vMachine.setRoom(machine.getRoom().getName());
                machineList.add(vMachine);
            }
            list.setMachineList(machineList);
            list.setTotal(machineList.size());
            return ResUtil.OK(list);
        }
        return ResUtil.ERROR("query错误");
    }
    @Override
    public ResJsonDTO getVNC(QueryDTO query){
        VMachine machine = machineRepo.findById(query.getMid()).orElse(null);
        if (machine == null) return ResUtil.ERROR("Can't find machine "+query.getMid());
        Teacher teacher = machine.getRoom().getTeacher();
        OSClientV3 os = OSFactory.builderV3()
                .endpoint(properties.getKeystoneAPI())
                .credentials(teacher.getUserID(),teacher.getPassword())
                .scopeToProject(Identifier.byId(teacher.getProjectID()))
                .authenticate();

        Server server = os.compute().servers().get(machine.getMid());
        if (server.getStatus().equals(Server.Status.ACTIVE)){
            VNCConsole console = os.compute().servers().getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);//instance is not ready
            return ResUtil.OK(console.getURL());
        }
        return ResUtil.ERROR("instance is not ready");
    }
    @Override
    public ResJsonDTO updateMachine(QueryDTO query){
        if (query.getMid() == null) {
            logService.addLog(new Log(
                    null,
                    query.getTid().toString()+query.getSid().toString(),
                    "更新虚拟机状态",
                    "失败",
                    null,
                    new Date()
            ));
            return ResUtil.ERROR("Update machine query error");
        }
        VMachine machine = machineRepo.findById(query.getMid()).orElse(null);
        if (machine == null) return ResUtil.ERROR("Can't find machine "+query.getMid());
        if (query.getStatus() != null) machine.setStatus(query.getStatus());
//        if (query.getProfile() != null)

        VMachine save = machineRepo.save(machine);
        logService.addLog(new Log(
                null,
                query.getMid(),
                "更新虚拟机状态",
                "成功",
                null,
                new Date()
        ));
        System.out.println("更新虚拟机成功:"+ save);
        return ResUtil.OK(query.getStatus());
    }
}
